﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace GeneralDashboard.Data
{
    public interface IDataUnit
    {
        dynamic GetValue();
        void SetValue(string value);
        void SetValue(byte[] hex);
    }

    public class DataUnit<T> : DataUnit, IDataUnit
    {
        public T Value { get; set; }

        private MethodInfo _stringValueParser;
        private MethodInfo _hexValueParser;

        public DataUnit()
        {
            Type = typeof(T);
            if(Type.FullName != typeof(string).FullName)
            {
                _stringValueParser = Type.GetMethod("Parse", new Type[] { typeof(string) });
                if (_stringValueParser == null)
                    throw new InvalidCastException($"Unsurpported type \"{Type.Name}\".");
                // TODO Hex数据写入DataUnit
            }
        }

        public dynamic GetValue()
        {
            return Value;
        }

        public void SetValue(string value)
        {
            if (Type.FullName == typeof(string).FullName)
                Value = (T)(object)value;
            else
                Value = (T)(_stringValueParser.Invoke(null, new object[] { value }));
        }

        public void SetValue(byte[] hex)
        {
            if (hex.Length == 1)
                Value = (T)(object)hex.First();
            else
            {
                Value = (T)typeof(BitConverter)
                            .GetMethod($"To{Type.Name}", new Type[] { typeof(ReadOnlySpan<byte>) })
                            .Invoke(null, new object[] { hex });
            }
        }
    }

    public class DataUnit
    {
        public Type Type { get; protected set; }
        public static IDataUnit Create(Type dataType)
        {
            if (dataType == typeof(sbyte))
                return new DataUnit<sbyte>();
            if (dataType == typeof(short))
                return new DataUnit<short>();
            if (dataType == typeof(int))
                return new DataUnit<int>();
            if (dataType == typeof(long))
                return new DataUnit<long>();
            if (dataType == typeof(byte))
                return new DataUnit<byte>();
            if (dataType == typeof(ushort))
                return new DataUnit<ushort>();
            if (dataType == typeof(uint))
                return new DataUnit<uint>();
            if (dataType == typeof(ulong))
                return new DataUnit<ulong>();
            if (dataType == typeof(float))
                return new DataUnit<float>();
            if (dataType == typeof(double))
                return new DataUnit<double>();
            if (dataType == typeof(bool))
                return new DataUnit<bool>();
            if (dataType == typeof(string))
                return new DataUnit<string>();
            throw new InvalidCastException($"Unsurpported type \"{dataType.Name}\".");
        }
    }
    
}
